﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Threading;

using SpotItComponents;
using SpotItServerAPI;

using Vitruvian.Serialization;
using Vitruvian.Services;
using Vitruvian.Testing;
using Vitruvian.Logging;

namespace SpotItServerTester
{
    [ContainsTests("SystemTest.DeckManagement")]
    public class DeckManagerTester : BaseTester
    {
        public DeckManagerTester() { }

        [OneTimeSetup]
        public void TestSuiteSetup()
        {
            base.EstablishConnectionToServer();

            base.WaitForAllDistributedServices();
            Assert.IsNotNull(accountManager);
            Assert.IsNotNull(deckManager);

            base.LoginInAsAdmin();
            Assert.IsNotNull(mySession);
            Assert.IsTrue(mySession.UserInfo.IsAdmin);

            // Remove all existing symbol sets
            OperationResult result = symbolManager.RemoveAllSymbolSets(mySession);
            Assert.IsTrue(result.Success);
        }


        [Test(1)]
        public void Test_SymbolSet_BasicOperations()
        {
            // Get the current full list of system sets
            OperationResult result = deckManager.Lookup(mySession, null, null, null);
            Assert.IsTrue(result.Success);
            List<Deck> origDecks = result.Data as List<Deck>;
            Assert.IsNotNull(origDecks);

            // CASE 1 - Add a simple deck
            // Create a symbol set locally, and then add it to the server via the symbol manager
            SymbolSet ss1 = new SymbolSet("My Favorite Symbols", true);
            ss1.AddSymbol(Symbol.CreateSymbolWithLabelImage("Alligator", new Bitmap("../../../Symbols/Alligator.jpg")));
            ss1.AddSymbol(Symbol.CreateSymbolWithLabelImage("Crab", new Bitmap("../../../Symbols/Crab.jpg")));
            ss1.AddSymbol(Symbol.CreateSymbolWithLabelImage("Dolphin", new Bitmap("../../../Symbols/Dolphin.jpg")));
            Assert.IsEqual(3, ss1.Symbols.Count);

            ss1.AddCategory(new Category("Test Category A"));
            ss1.AddCategory(new Category("Test Category B"));
            Assert.IsEqual(2, ss1.Categories.Count);

            // CASE 1 - Create a simple deck using a symbol set
            Image backImage = new Bitmap("../../../Symbols/Background-1.jpg");
            Deck deck1 = new Deck("Test Deck 1", true, backImage);
            DeckSetupDirectorUsingRandomSymbols setupDirector = new DeckSetupDirectorUsingRandomSymbols();
            setupDirector.FromSymbolSet = ss1;
            setupDirector.TargetDeck = deck1;
            setupDirector.Setup();

            // Add the deck to the server via the symbol manager, then make sure it is there
            // by getting the new full list of system sets and seeing if the new set is in that list
            result = deckManager.Add(mySession, deck1);
            Assert.IsTrue(result.Success);

            result = deckManager.Lookup(mySession, null, null, null);
            Assert.IsTrue(result.Success);
            List<Deck> newDecks = result.Data as List<Deck>;
            Assert.IsNotNull(newDecks);
            Assert.IsEqual(origDecks.Count + 1, newDecks.Count);
            Assert.IsTrue(newDecks.Contains(deck1));

            // TODO: finish test case by writing assertions

            // CASE 2 - Add a copy of symbol set
            Deck deck2 = new Deck("Copy of Test Deck 1", false, deck1);
            result = deckManager.Add(mySession, deck2);
            Assert.IsTrue(result.Success);

            result = deckManager.Lookup(mySession, null, null, null);
            Assert.IsTrue(result.Success);
            newDecks = result.Data as List<Deck>;
            Assert.IsNotNull(newDecks);
            Assert.IsEqual(origDecks.Count + 2, newDecks.Count);
            Assert.IsTrue(newDecks.Contains(deck2));

            // CASE 3 - Add another copy of symbol set
            Deck deck3 = new Deck("Another Copy of My Favorite Symbols", false, deck1);
            result = deckManager.Add(mySession, deck3);
            Assert.IsTrue(result.Success);

            result = deckManager.Lookup(mySession, null, null, null);
            Assert.IsTrue(result.Success);
            newDecks = result.Data as List<Deck>;
            Assert.IsNotNull(newDecks);
            Assert.IsEqual(origDecks.Count + 3, newDecks.Count);
            Assert.IsTrue(newDecks.Contains(deck3));

            // CASE 4 - Try to add an null
            result = symbolManager.Add(mySession, null);
            Assert.IsFalse(result.Success);

            // CASE 5 - Remove ss2
            result = deckManager.Remove(mySession, deck2);
            Assert.IsTrue(result.Success);
            result = deckManager.Lookup(mySession, null, null, null);
            Assert.IsTrue(result.Success);
            newDecks = result.Data as List<Deck>;
            Assert.IsNotNull(newDecks);
            Assert.IsEqual(origDecks.Count + 2, newDecks.Count);
            Assert.IsFalse(newDecks.Contains(deck2));

            // CASE 6 - Update deck1
            deck1.Cards.Add(new Card());
            deck1.Categories.Add(new Category("Test Category C"));
            result = deckManager.Update(mySession, deck1);
            Assert.IsTrue(result.Success);

            // CASE 7 - Lookup deck1 from the Server
            result = deckManager.Lookup(mySession, deck1.Id);
            Assert.IsTrue(result.Success);
            Deck deck1a = result.Data as Deck;
            Assert.IsEqual(deck1.Id, deck1a.Id);
            Assert.IsEqual(deck1.Label, deck1a.Label);
            Assert.IsEqual(deck1.Cards.Count, deck1a.Cards.Count);
            Assert.IsEqual(deck1.Categories.Count, deck1a.Categories.Count);

            // CASE 8 - Try to update an non-existing symbol set
            result = deckManager.Update(mySession, deck2);
            Assert.IsFalse(result.Success);

        }

        [Test(5)]
        public void Test_SymbolSet_ChangeOwner()
        {
            // TODO:
        }

        [Test(6)]
        public void Test_SymbSet_RemoveAllSymbolSets()
        {
            // TODO:
        }

    }
}
